///@file Tensor3.cpp
///@brief Implementation of the class representing a third order tensor
///@author Arnaud Duval
///@version 0.0
///@date 2009/10/19


#include "Tensor3.h"

///@brief Default constructor
Tensor3::Tensor3()
{
	size = 0;
}

///@brief Constructor giving the dimension
///@param s size of the tensor
Tensor3::Tensor3(int s)
{
	assert(s > 0);
	size = s;
	t = new Tensor2[s];
	for(int i = 0 ; i < s ; i++)
	{
		t[i] = Tensor2(s);
	}	
}

///@brief Copy constructor
///@param tens Tensor3 object to copy
Tensor3::Tensor3(const Tensor3 &tens)
{
	size = tens.size;
	t = new Tensor2[size];
	for(unsigned int i = 0 ; i < size ; i++)
	{
		t[i] =tens.t[i];
	}
}

///@brief Copy constructor with temporary object
///@param tens Temporary Tensor3 object to copy
Tensor3::Tensor3(Tensor3 *tens)
{
	size = (*tens).size;
	t = new Tensor2[size];
	for(unsigned int i = 0 ; i < size ; i++)
	{
		t[i] = (*tens).t[i];
	}
}

///@brief Destructor
Tensor3::~Tensor3()
{
	if(size)
		delete[] t;
	size = 0;
}

///@brief Overload of () operator
double& Tensor3::operator()(unsigned int i, unsigned int j, unsigned int k)
{
	assert((i > 0)&&(i <= size));
	assert((j > 0)&&(j <= size));
	assert((k > 0)&&(k <= size));
	return (t[i-1])(j,k);
}

///@brief Overload of = operator
///@param tens Tensor3 object to copy
Tensor3& Tensor3::operator = (const Tensor3 tens)
{
	assert (tens.size != 0);
	size = tens.size;
	t = new Tensor2[size];
	for(unsigned int i = 0 ; i < size ; i++)
		t[i] = tens.t[i];
	return (*this);
}


///@brief Overload of = operator for temporary objects
///@param tens Pointer to Tensor3 object to copy
Tensor3& Tensor3::operator = (Tensor3* tens)
{
	assert ((*tens).size != 0);
	size = (*tens).size;
	t = new Tensor2[size];
	for(unsigned int i = 0 ; i < size ; i++)
		t[i] = (*tens).t[i];
	return (*this);
}

///@brief Overload of += operator
///@param tens Third order tensor to add to current one
void Tensor3::operator += (const Tensor3& tens)
{
	assert(size == tens.size);
	for(unsigned int i = 0 ; i < size ; i++)
		t[i] += tens.t[i];
}


///@brief Overload of -= operator
///@param tens Third order tensor to substract to current one
void Tensor3::operator -= (const Tensor3& tens)
{
	assert(size == tens.size);
	for(unsigned int i = 0 ; i < size ; i++)
		t[i] -= tens.t[i];
}

///@brief Overload of + operator : addition of 2 Tensor3
///@param t1 left hand operand : Tensor3
///@param t2 right hand operand : Tensor3
Tensor3 operator + (const Tensor3& t1, const Tensor3& t2)
{
	assert(t1.size == t2.size);
	Tensor3 res(t1.size);
	for(unsigned int i = 0 ; i < t1.size ; i++)
		res.t[i] &= (t1.t[i] + t2.t[i]);
	return res;
}

///@brief Overload of - operator : substraction of 2 Tensor3
///@param t1 left hand operand : Tensor3
///@param t2 right hand operand : Tensor3
Tensor3 operator - (const Tensor3& t1, const Tensor3& t2)
{
	assert(t1.size == t2.size);
	Tensor3 res(t1.size);
	for(unsigned int i = 0 ; i < t1.size ; i++)
		res.t[i] &= t1.t[i] - t2.t[i];
	return res;
}

///@brief Overload of * operator : product Tensor3 - scalar
///@param t left hand operand : Tensor3
///@param s right hand operand : scalar
Tensor3 operator * (const Tensor3& t, const double& s)
{
	Tensor3 res(t.size);
	for(unsigned int i = 0 ; i < t.size ; i++)
		res.t[i] &= t.t[i]*s;
	return res;
}

///@brief Overload of * operator : product scalar - tensor3
///@param s left hand operand : scalar
///@param t right hand operand : Tensor3
Tensor3 operator * (const double& s, const Tensor3& t)
{
	Tensor3 res(t.size);
	for(unsigned int i = 0 ; i < t.size ; i++)
		res.t[i] &= t.t[i]*s;
	return res;
}

///@brief Overload of / operator : division by a scalar
///@param t left hand operand : Tensor3
///@param s right hand operand : scalar
Tensor3 operator / (const Tensor3& t, const double& s)
{
	assert(s != 0.);
	Tensor3 res(t.size);
	for(unsigned int i = 0 ; i < t.size ; i++)
		res.t[i] &= t.t[i] / s;
	return res;
}

///@brief Overload of << operator
///@param s out stream
///@param t Tensor3
std::ostream& operator<<(std::ostream &s, const Tensor3& t)
{
	for(unsigned int i = 0 ; i < t.size ; i++)
	{
		s << t.t[i] << "\n";
		if(i != t.size -1)
			s << "\n";
	}
	return s;
}

